/*
 * Copyright (c) 2019-2020, https://api.iot.10086.cn/(https://gitee.com/cmcc-iot-api/iot-card-open-application/).
 */
package cn.iot.card.open.tariff.service;

import cn.iot.card.open.constants.Constants;
import cn.iot.card.open.constants.ErrorCode;
import cn.iot.card.open.constants.UrlConstants;
import cn.iot.card.open.context.LoginContextHolder;
import cn.iot.card.open.context.model.LoginUser;
import cn.iot.card.open.ec.dto.ResponseDto;
import cn.iot.card.open.exception.enums.BizExceptionEnum;
import cn.iot.card.open.modular.entity.Card;
import cn.iot.card.open.modular.entity.UserGroupRl;
import cn.iot.card.open.modular.model.ResultDTO;
import cn.iot.card.open.modular.service.CardService;
import cn.iot.card.open.modular.service.UserService;
import cn.iot.card.open.modular.token.TokenService;
import cn.iot.card.open.pojo.page.LayuiPageFactory;
import cn.iot.card.open.pojo.page.LayuiPageInfo;
import cn.iot.card.open.tariff.dto.*;
import cn.iot.card.open.util.ApiRequestUtil;
import cn.iot.card.open.util.CommonUtil;
import cn.iot.card.open.util.JsonUtil;
import cn.stylefeng.roses.core.util.ToolUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 资费信息业务操作
 *
 * @author 何光鑫
 * @date 20200221 10:39:44
 * @modify 20200221 何光鑫 v1.1.1 创建
 * @since v1.1.1
 */
@Service
@Slf4j
public class OrderedChargesService {

    /**
     * 是否是最后一页
     */
    private static final String LASTPAGEFLAG = "N";

    /**
     * 上一次的页码
     */
    private long prePage = 1;

    /**
     * 上一次的总数
     */
    private long preTotal = 0;

    /**
     * 上一次的页条数
     */
    private long preSize = 0;

    @Autowired
    private ApiRequestUtil apiRequestUtil;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private CardService cardService;

    @Autowired
    private UserService userService;

    /**
     * 调用api接口查询可订购资费目录节点
     *
     * @param transId
     * @param accountId  集团id
     * @param status     资费类别：1-集团资费，2-群组资费，3-用户资费
     * @return 返回 long
     * @throws IOException
     * @author 何光鑫
     * @date 20200221 11:30:59
     * @modify 20200221 何光鑫 v1.1.1 创建
     * @since v1.1.1
     */
    public LayuiPageInfo queryCategories(String transId, String accountId , String status) throws IOException {

        Page page = LayuiPageFactory.defaultPage();
        if (StringUtils.isBlank(accountId)) {
            log.warn("[{}] queryCategories accountId is null.", transId);
            return LayuiPageFactory.createEmptyPageInfo();
        }
        //封装请求参数
        Map<String, String> parameterMap = new HashMap<>();
        String url = UrlConstants.QUERY_CATEGORIES;
        parameterMap.put(Constants.REQUEST_QUERY_SCENES, status);
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO tokenResultDTO = doRequest(true, accountId, transId,parameterMap,url);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
            return LayuiPageFactory.cteateErrorMsg(errorCode);
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = tokenResultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token[accountId:{}] of queryCategories is invalid and start to get a new token.", transId, accountId);
            tokenResultDTO = doRequest(false, accountId, transId, parameterMap, url);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
                return LayuiPageFactory.cteateErrorMsg(errorCode);
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = tokenResultDTO.getMsg();
        }
        log.info("[{}] query categories result string is {}.", transId, responseStr);
        // 组装页面信息
        ResponseDto<CategoriesListDTO> result = JsonUtil.parseJson(responseStr, new TypeReference<ResponseDto<CategoriesListDTO>>() {});
        code = result.getStatus();
        if (!ErrorCode.SUCCESS.getCode().equals(code)) {
            // 如果api接口返回失败，则返回失败原因
            log.warn("[{}] query categories error,error message is {}.", transId, result.getMessage());
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.getByCode(code));
        }
        CategoriesListDTO categoriesListDTO = result.getResult().get(0);
        if (ToolUtil.isEmpty(categoriesListDTO)) {
            log.warn("[{}] query categories end,result is null.", transId);
            return LayuiPageFactory.createEmptyPageInfo();
        }
        List<CategoriesDTO> categoryList = categoriesListDTO.getCategoryList();
        page.setTotal(categoryList.size());
        page.setRecords(categoryList);
        return LayuiPageFactory.createPageInfo(page);
    }

    /**
     * 查询可订购资费
     *
     * @param accountId  集团id
     * @param status     资费类别：1-集团资费，2-群组资费，3-用户资费
     * @param groupId    群组id
     * @param msisdn     卡号
     * @param catalogId  目录ID
     * @param categoryId  节点ID
     * @return 返回 layui page info
     * @throws IOException
     * @author 何光鑫
     * @date 20200225 15:33:41
     * @modify 20200225 何光鑫 v1.1.1 创建
     * @since v1.1.1
     */
    public LayuiPageInfo queryPurchasableOfferings(String accountId ,String status,String groupId,String msisdn,String catalogId,String categoryId) throws IOException {
        Map<String, String> parameterMap = new HashMap<>();
        //公共请求参数
        Page page = LayuiPageFactory.defaultPage();
        parameterMap.put(Constants.REQUEST_QUERY_TYPE, status);
        parameterMap.put(Constants.REQUEST_CATALOG_ID, catalogId);
        parameterMap.put(Constants.REQUEST_CATEGORY_ID, categoryId);
        String startNum = String.valueOf(page.getCurrent());
        String pageSize = String.valueOf(page.getSize());
        parameterMap.put(Constants.REQUEST_PARAM_STARTNUM, startNum);
        parameterMap.put(Constants.REQUEST_PARAM_PAGESIZE, pageSize);
        //如果为群组资费
        if(status.equals(Constants.STATUS_GROUP) && !groupId.equals(Constants.FRONT_REQUEST_NULL)){
            parameterMap.put(Constants.REQUEST_GROUP_ID, groupId);
        }
        //如果为用户资费
        if(status.equals(Constants.STATUS_USER) && !msisdn.equals(Constants.FRONT_REQUEST_NULL)){
            parameterMap.put(Constants.REQUEST_PARAM_MSISDN, msisdn);
            Card card = cardService.getBaseMapper().findCard(msisdn, Constants.REQUEST_PARAM_MSISDN);
            if(ToolUtil.isNotEmpty(card)){
                // 验证当前用户是否有卡权限
                LoginUser loginUser = LoginContextHolder.getContext().getUser();
                UserGroupRl userGroupRl = userService.getUserGroupRlByUserAndCard(loginUser.getId(), card.getCardId());
                if (null == userGroupRl) {
                    return LayuiPageFactory.createBizExceptionMsg(BizExceptionEnum.CARD_NOT_BELONG_USER);
                }
                // 根据卡号查账户
                Map<String, Object> cardDtoMap = cardService.getCardInfo(card.getCardId());
                Object accountIdObj = cardDtoMap.get(Constants.REQUEST_ACCOUNT_ID);
                if (ToolUtil.isEmpty(accountIdObj)) {
                    // 当前卡未绑定任何账户
                    return LayuiPageFactory.cteateErrorMsg(ErrorCode.ERR11047);
                }
                accountId = String.valueOf(accountIdObj);
            }
        }
        String transId = CommonUtil.generateTransId(accountId);
        if (StringUtils.isBlank(accountId)) {
            log.warn("[{}] accountId is null.", transId);
            return LayuiPageFactory.createEmptyPageInfo();
        }
        //封装请求参数
        String url = UrlConstants.QUERY_PURCHASABLE_OFFERINGS;
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO tokenResultDTO = doRequest(true, accountId, transId,parameterMap,url);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
            return LayuiPageFactory.cteateErrorMsg(errorCode);
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = tokenResultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token[accountId:{}] is invalid and start to get a new token.", transId, accountId);
            tokenResultDTO = doRequest(false, accountId, transId, parameterMap, url);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                ErrorCode errorCode = ErrorCode.getByCode(tokenResultDTO.getCode());
                return LayuiPageFactory.cteateErrorMsg(errorCode);
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = tokenResultDTO.getMsg();
        }

        log.info("[{}] query PurchasableOfferings result string is {}.", transId, responseStr);
        // 组装页面信息
        ResponseDto<PurchasableOfferingsDTO> result = JsonUtil.parseJson(responseStr, new TypeReference<ResponseDto<PurchasableOfferingsDTO>>() {});
        code = result.getStatus();
        if (!ErrorCode.SUCCESS.getCode().equals(code)) {
            // 如果api接口返回失败，则返回失败原因
            log.warn("[{}] query PurchasableOfferings error,error message is {}.", transId, result.getMessage());
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.getByCode(code));
        }
        List<PurchasableOfferingsDTO> purchasableOfferingsDTOList = result.getResult();
        if (ToolUtil.isEmpty(purchasableOfferingsDTOList)) {
            log.warn("[{}] query PurchasableOfferings end,result is null.", transId);
            return LayuiPageFactory.createEmptyPageInfo();
        }
        PurchasableOfferingsDTO purchasableOfferingsDTO = purchasableOfferingsDTOList.get(0);
        List<OfferingInfoDTO> offeringInfoList = purchasableOfferingsDTO.getOfferingInfoList();
        List<OfferingsResponseDTO> responseDTOS = new ArrayList<>();
        if(ToolUtil.isNotEmpty(offeringInfoList)){
            for(OfferingInfoDTO offeringInfoDTO:offeringInfoList){
                OfferingsResponseDTO offeringsResponseDTO = new OfferingsResponseDTO();
                offeringsResponseDTO.setOfferingId(offeringInfoDTO.getOfferingId());
                offeringsResponseDTO.setOfferingName(offeringInfoDTO.getOfferingName());
                offeringsResponseDTO.setOfferingType(offeringInfoDTO.getOfferingType());
                offeringsResponseDTO.setPaymentMode(offeringInfoDTO.getPaymentMode());
                offeringsResponseDTO.setEffectiveDate(offeringInfoDTO.getEffectiveDate());
                offeringsResponseDTO.setExpiriedDate(offeringInfoDTO.getExpiriedDate());
                offeringsResponseDTO.setDescription(offeringInfoDTO.getDescription());
                if(ToolUtil.isNotEmpty(offeringInfoDTO.getChildOfferList())){
                    List<ChildOfferDTO> childOfferList = offeringInfoDTO.getChildOfferList();
                    for(ChildOfferDTO childOfferDTO:childOfferList){
                        offeringsResponseDTO.setChildOfferId(childOfferDTO.getChildOfferId());
                        offeringsResponseDTO.setChildOfferName(childOfferDTO.getChildOfferName());
                        offeringsResponseDTO.setChildEffectiveDate(childOfferDTO.getEffectiveDate());
                        offeringsResponseDTO.setChildExpiriedDate(childOfferDTO.getExpiriedDate());
                        responseDTOS.add(offeringsResponseDTO);
                    }
                }else{
                    offeringsResponseDTO.setChildOfferId("");
                    offeringsResponseDTO.setChildOfferName("");
                    offeringsResponseDTO.setChildEffectiveDate("");
                    offeringsResponseDTO.setChildExpiriedDate("");
                    responseDTOS.add(offeringsResponseDTO);
                }
            }
        }
        // 后一页
        if (page.getCurrent() > prePage) {
            if (LASTPAGEFLAG.equals(purchasableOfferingsDTO.getFlag())) {
                // 如果不是最后一页，设置总数超过当前数，点亮下一页按钮
                preTotal = preSize * page.getCurrent();
                page.setTotal(preTotal + 1);
            } else {
                preTotal = responseDTOS.size() + preSize * prePage;
                page.setTotal(preTotal);
            }
        } else if (page.getCurrent() == 1){
            // 第一页
            preSize = responseDTOS.size();
            if (LASTPAGEFLAG.equals(purchasableOfferingsDTO.getFlag())) {
                // 如果不是最后一页，设置总数超过当前数，点亮下一页按钮
                page.setTotal(preSize + 1);
            } else {
                page.setTotal(preSize);
            }
            preTotal = preSize;
        } else {
            // 前一页
            page.setTotal(preTotal);
        }
        prePage = page.getCurrent();
        preSize = responseDTOS.size();
        page.setRecords(responseDTOS);
        return LayuiPageFactory.createPageInfo(page);
    }

    /**
     * 封装参数
     *
     * @param tokenValid   true表示使用已经初始化了的token值，false表示使用重新生成的token值
     * @param accountId 集团id
     * @param transId
     * @param parameterMap 调用api接口的参数
     * @param url 调用API接口的请求路径
     * @return 返回 API接口响应结果（或者获取token失败的原因）
     * @throws IOException
     * @author 何光鑫
     * @date 20200108 17:29:12
     * @modify 20200108 何光鑫 v1.0 创建
     * @since v1.0
     */
    private ResultDTO doRequest(boolean tokenValid, String accountId, String transId,Map<String, String> parameterMap,String url) throws IOException {
        // 根据 accountId 查询 token
        ResultDTO tokenResultDTO = tokenService.getToken(tokenValid, accountId);
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            return tokenResultDTO;
        }
        parameterMap.put(Constants.REQUEST_PARAM_TOKEN, tokenResultDTO.getMsg());
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        String methodUrl = apiRequestUtil.buildRequestUrl(parameterMap, url);
        log.info("[{}] request url is {}.", transId, methodUrl);

        tokenResultDTO.setMsg(apiRequestUtil.doGet(methodUrl));
        return tokenResultDTO;
    }
}
